package com.atguigu.tingshu.user.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
import com.atguigu.tingshu.common.util.MongoUtil;
import com.atguigu.tingshu.model.user.UserListenProcess;
import com.atguigu.tingshu.user.service.UserListenProcessService;
import com.atguigu.tingshu.vo.album.TrackStatMqVo;
import com.atguigu.tingshu.vo.user.UserListenProcessVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;


@Service
@SuppressWarnings({"all"})
public class UserListenProcessServiceImpl implements UserListenProcessService {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RabbitService rabbitService;


    /**
     * 获取声音的上次退出时间
     * @param trackId
     * @return
     */

    @Override
    public BigDecimal getTrackBreakSecond(Long trackId, Long userId) {
        // 1.构建查询条件
        Query query = new Query(Criteria.where("userId").is(userId).and("trackId").is(trackId));

        // 2.执行查询播放进度
        UserListenProcess userListenProcess = mongoTemplate.findOne(
                query,
                UserListenProcess.class,
                MongoUtil.getCollectionName(MongoUtil.MongoCollectionEnum.USER_LISTEN_PROCESS, userId)
        );

        if (userListenProcess != null) {
            return userListenProcess.getBreakSecond();
        }


        return new BigDecimal("0.00");
    }

    /**
     * 更新当前用户收听声音播放进度
     * @param userListenProcessVo
     * @return
     */
    @Override
    public void updateListenProcess(Long userId, UserListenProcessVo userListenProcessVo) {
        // 设置数据库查询条件 userId trackId
        Query query = new Query(Criteria.where("userId").is(userId).and("trackId").is(userListenProcessVo.getTrackId()));

        // 设置只查询出一个声音进度，避免声音重复暂停时，不断的更新播放声音进度
        query.limit(1);

        // 从 MongoDB 中获取声音播放进度
        UserListenProcess userListenProcess = mongoTemplate.findOne(
                query,
                UserListenProcess.class,
                /*MongoUtil是一个工具类，用于处理MongoDB数据库的连接、查询、插入、更新和删除等操作。*/
                MongoUtil.getCollectionName/*这是MongoUtil类中的一个方法，用于获取指定集合的名称*/
                        (MongoUtil.MongoCollectionEnum.USER_LISTEN_PROCESS/*表示获取MongoDB数据库中的一个名为USER_LISTEN_PROCESS的集合*/
                                ,userId)
        );

        // 判断该用户在此声音中是否有播放记录
        if (null == userListenProcess){
            // 如果不存在则新增播放进度
            userListenProcess = new UserListenProcess();
            BeanUtils.copyProperties(userListenProcessVo,userListenProcess);

            userListenProcess.setUserId(userId);

            userListenProcess.setIsShow(1);

            userListenProcess.setCreateTime(new Date());
            userListenProcess.setUpdateTime(new Date());

        } else {
            // 如果存在则更新进度
            userListenProcess.setBreakSecond(userListenProcessVo.getBreakSecond());
            userListenProcess.setUpdateTime(new Date());
        }

        // 将修改完的数据重新存入 MongoDB
        mongoTemplate.save(userListenProcess,MongoUtil.getCollectionName(MongoUtil.MongoCollectionEnum.USER_LISTEN_PROCESS,userId));

        // 采用 Redis 提供 set k v nx ex 确保在规定时间内（24小时）播放统计次数 一次

        String key = RedisConstant.USER_TRACK_REPEAT_STAT_PREFIX + userId + ":" + userListenProcessVo.getTrackId();

        long ttl = DateUtil.endOfDay(new Date()).getTime() - System.currentTimeMillis();

        Boolean flag = redisTemplate.opsForValue().setIfAbsent(key ,userListenProcess.getTrackId(),ttl, TimeUnit.MILLISECONDS);

        if (flag){
            // 如果设置成功，发送消息到rabbitmq消息队列
            // 构建更新声音进度 MQVO对象
            TrackStatMqVo trackStatMqVo = new TrackStatMqVo();

            trackStatMqVo.setBusinessNo(IdUtil.fastSimpleUUID());
            trackStatMqVo.setAlbumId(userListenProcess.getAlbumId());
            trackStatMqVo.setTrackId(userListenProcess.getTrackId());
            trackStatMqVo.setStatType(SystemConstant.TRACK_STAT_PLAY);
            trackStatMqVo.setCount(1);
            // 如果设置成功，发送消息到rabbitmq消息队列
            rabbitService.sendMessage(MqConst.EXCHANGE_USER,MqConst.ROUTING_TRACK_STAT_UPDATE, JSON.toJSONString(trackStatMqVo));
        }


    }

    @Override
    public Map<String, Long> getLatelyTrack(Long userId) {

        // 从MongoDB中获取用户在该专辑中最后一次播放的声音
        // 构建查询条件
        Query query = new Query(Criteria.where("userId").is(userId));

        query.with(Sort.by(Sort.Direction.DESC,"updateTime"));

        query.limit(1);

        UserListenProcess listenProcess = mongoTemplate.findOne(
                query,
                UserListenProcess.class,
                MongoUtil.getCollectionName(MongoUtil.MongoCollectionEnum.USER_LISTEN_PROCESS,userId)
        );

        // 如果可以从MongoDB查询到数据则封装响应结果
        if (null != listenProcess){
            Map resultMap = new HashMap<>();

            resultMap.put("albumId",listenProcess.getAlbumId());
            resultMap.put("trackId",listenProcess.getTrackId());

            return resultMap;
        }

        return null;
    }
}
